home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / cpp112.zoo / src / main.c < prev    next >
C/C++ Source or Header  |  1994-07-07  |  9KB  |  393 lines

  1. /*---------------------------------------------------------------------*\
  2. |                                    |
  3. | CPP -- a stand-alone C preprocessor                    |
  4. | Copyright (c) 1993 Hacker Ltd.        Author: Scott Bigham    |
  5. |                                    |
  6. | Permission is granted to anyone to use this software for any purpose    |
  7. | on any computer system, and to redistribute it freely, with the    |
  8. | following restrictions:                        |
  9. | - No charge may be made other than reasonable charges for repro-    |
  10. |     duction.                                |
  11. | - Modified versions must be clearly marked as such.            |
  12. | - The author is not responsible for any harmful consequences of    |
  13. |     using this software, even if they result from defects therein.    |
  14. |                                    |
  15. | main.c -- kick it all off                        |
  16. \*---------------------------------------------------------------------*/
  17.  
  18. #include <stdio.h>
  19. #include <stddef.h>
  20. #include <stdlib.h>
  21. #include <signal.h>
  22. #include <time.h>
  23. #include <unistd.h>
  24. #include "global.h"
  25. #include "ztype.h"
  26. #include "patchlev.h"
  27.  
  28. #define DEFAULT_CONFIG_NAME "cpp_defs.h"
  29.  
  30. FILE *outf = stdout;
  31. FILE *inf = NULL;
  32. char *argv0;
  33. char **I_list;
  34. char date_string[12], time_string[9];
  35. int nerrs;
  36.  
  37. int sl_style = SL_NORMAL,
  38.     keep_comments = 0,
  39.     do_trigraphs = 0,
  40.     ansi = 0,
  41.     w_bad_chars = 1,
  42.     w_nest_cmts = 0,
  43.     f_cpp_cmts = 0,
  44.     w_bad_concat = 1;
  45.  
  46. int in_config_file = 0;
  47. static char *config_file_name = NULL;
  48. static char stdin_name[] = STDIN_NAME;
  49.  
  50. int fluff_mode = 0;
  51.  
  52. static void usage()
  53. {
  54.   fprintf(stderr, "usage: %s [-Dname[=value]...] [-Uname] "
  55.       "[ infile [ outfile ] ]\n", argv0
  56.   );
  57.   exit(1);
  58. }
  59.  
  60. static void dammit(sig)
  61.   int sig;
  62. {
  63.   fatal("received signal %d", sig);
  64. }
  65.  
  66. static void setup_signals()
  67. {
  68.   (void)signal(SIGHUP, dammit);
  69.   (void)signal(SIGINT, dammit);
  70.   (void)signal(SIGQUIT, dammit);
  71.   (void)signal(SIGILL, dammit);
  72.   (void)signal(SIGTRAP, dammit);
  73.   (void)signal(SIGABRT, dammit);
  74.   (void)signal(SIGEMT, dammit);
  75.   (void)signal(SIGFPE, dammit);
  76.   (void)signal(SIGBUS, dammit);
  77.   (void)signal(SIGSEGV, dammit);
  78.   (void)signal(SIGSYS, dammit);
  79.   (void)signal(SIGPIPE, dammit);
  80.   (void)signal(SIGALRM, dammit);
  81.   (void)signal(SIGTERM, dammit);
  82. }
  83.  
  84. /* add_include() -- adds |path| to the list of include directories */
  85. static void add_include(path)
  86.   char *path;
  87. {
  88.   static char **cur_I = NULL;
  89.   static int n_I;
  90.   ptrdiff_t dp;
  91.  
  92.   if (!cur_I)
  93.     cur_I = I_list = (char **)mallok((n_I = 3) * sizeof (char *));
  94.  
  95.   if (cur_I - I_list == n_I) {
  96.     dp = cur_I - I_list;
  97.     I_list = reallok(I_list, (n_I *= 2) * sizeof (char *));
  98.  
  99.     cur_I = I_list + dp;
  100.   }
  101.   *cur_I++ = path;
  102. }
  103.  
  104. /* long_option() -- parses long option |s| */
  105. static void long_option(s)
  106.   char *s;
  107. {
  108.   int yesno = 1;
  109.   char *t;
  110.  
  111.   if (*s == 'W' || *s == 'f') {
  112.     if (s[1] == 'n' && s[2] == 'o' && s[3] == '-') {
  113.       yesno = 0;
  114.       t = s + 4;
  115.     } else
  116.       t = s + 1;
  117.     if (*s == 'W') {        /* warnings */
  118.       if (streq(t, "bad-chars"))
  119.     w_bad_chars = yesno;
  120.       else if (streq(t, "nested-comments"))
  121.     w_nest_cmts = yesno;
  122.       else if (streq(t, "bad-concat-tokens"))
  123.     w_bad_concat = yesno;
  124.       else {
  125.     error("unknown -W option:  %s", t);
  126.     usage();
  127.       }
  128.     } else {            /* actions */
  129.       if (streq(t, "c++-comments"))
  130.     f_cpp_cmts = yesno;
  131.       else {
  132.     error("unknown -f option:  %s", t);
  133.     usage();
  134.       }
  135.     }
  136.   } else if (*s == 'X') {
  137.     if (streq(s + 1, "fluff"))
  138.       fluff_mode = 1;
  139.     else {
  140.       error("unknown -X option:  %s", s + 1);
  141.       usage();
  142.     }
  143.   } else if (streq(s, "ansi")) {
  144.     ansi = 1;
  145.     do_trigraphs ^= 1;
  146.   } else {
  147.     error("unrecognized option -%s", s);
  148.     usage();
  149.   }
  150. }
  151.  
  152. /*
  153.    opt_define() -- handle -Dfred.  |s| points to the beginning of the token
  154.    to #define.
  155. */
  156. static void opt_define(s)
  157.   char *s;
  158. {
  159.   Macro *M, *M1;
  160.   char *t;
  161.   unsigned int hv;
  162.   int hmm = 0;
  163.   static char one[] = "1";
  164.  
  165.   hv = hash_id(s, &t);
  166.   if (*t && *t != '=') {
  167.     error("malformed -D option \"%s\"", s);
  168.     return;
  169.   }
  170.   if (*t)
  171.     *t++ = '\0';
  172.   else
  173.     t = one;
  174.   M1 = mk_Macro();
  175.   M1->m_text = tokenize_string(t);
  176.   if ((M = lookup(s, hv))) {
  177.  
  178.     /*
  179.        guard against re-#definition of magic tokens or previously -U'd tokens
  180.     */
  181.     if (M->flags & (UNDEF | MAGIC))
  182.       hmm = 1;
  183.     if (hmm || !macro_eq(M1, M)) {
  184.       if (!hmm)
  185.     error("non-identical redefinition of \"%s\"", s);
  186.     }
  187.     free_Macro(M1);
  188.     return;
  189.   }
  190.   hash_add(s, hv, M1);
  191. }
  192.  
  193. /*
  194.    opt_undefine() -- handle -Ufred.  |s| points to the beginning of the token
  195.    to #undef.
  196. */
  197. static void opt_undefine(s)
  198.   char *s;
  199. {
  200.   Token T;
  201.   Macro *M;
  202.   int was_there = 0;
  203.   unsigned int hv;
  204.  
  205.   hv = hash_id(s, NULL);
  206.   if ((M = lookup(s, hv))) {
  207.     if (M->flags & MAGIC)
  208.       return;
  209.     if (M->m_text)
  210.       free_tlist(M->m_text);
  211.     was_there = 1;
  212.   } else {
  213.     M = mk_Macro();
  214.   }
  215.   M->m_text = NULL;
  216.   M->flags |= UNDEF;
  217.   if (!was_there)
  218.     hash_add(s, hv, M);
  219. }
  220.  
  221. /* do_cmdline_arg() -- process the command-line argument |s| */
  222. void do_cmdline_arg(arg)
  223.   register char *arg;
  224. {
  225.   switch (arg[1]) {
  226.   case 'P':
  227.     switch (arg[2]) {
  228.     case '0':
  229.     case '\0':
  230.       sl_style = SL_NONE;
  231.       break;
  232.     case '1':
  233.       sl_style = SL_NORMAL;
  234.       break;
  235.     case '2':
  236.       sl_style = SL_LINE;
  237.       break;
  238.     default:
  239.       error("bad argument '%c' to -P option", arg[2]);
  240.     }
  241.     break;
  242.   case 'C':
  243.     keep_comments = 1;
  244.     break;
  245.   case 'T':
  246.     do_trigraphs ^= 1;
  247.     break;
  248.   case 'I':
  249.     add_include(copy_filename(arg + 2, 0));
  250.     break;
  251.   case 'D':
  252.     opt_define(arg + 2);
  253.     break;
  254.   case 'U':
  255.     opt_undefine(arg + 2);
  256.     break;
  257.   case 'V':
  258.     fprintf(stderr, "CPP -- C preprocessor v%d.%d.%d\n"
  259.         "(c) 1993,94 Hacker Ltd., all rights reserved\n",
  260.         CPP_VERSION, CPP_RELEASE, CPP_PATCHLEVEL);
  261.     break;
  262.   case 'S':            /* already handled elsewhere */
  263.     break;
  264.   default:
  265.     long_option(arg + 1);
  266.   }
  267. }
  268.  
  269. /* do_all_cmdline_args() -- process all command_line arguments */
  270. static int Argc = 0;
  271. static char **Argv = 0;
  272. int Argc_end = 0;
  273.  
  274. void do_all_cmdline_args()
  275. {
  276.   int i;
  277.  
  278.   for (i = 1; i < Argc && *Argv[i] == '-' && Argv[i][1] != '\0'; i++)
  279.     do_cmdline_arg(Argv[i]);
  280.   hash_clean_undef();
  281.   Argc_end = i;
  282. }
  283.   
  284. /* do_config_file() -- read standard #define's from config file */
  285. static void do_config_file()
  286. {
  287.   char buf[128];
  288.   register const char *s;
  289.   register int len;
  290.  
  291.   if (!config_file_name) {    /* default config file */
  292.     if (!(s = getenv("LIB")))
  293.       s = ".";
  294.     while (*s) {
  295.       len = strcspn(s, ",;");
  296.       strncpy(buf, s, len);
  297.       buf[len] = PATH_SEP;
  298.       strcpy(buf + len + 1, DEFAULT_CONFIG_NAME);
  299.       if (access(buf, R_OK) == 0) {
  300.     in_config_file = 1;
  301.     process_file(buf);
  302.     in_config_file = 0;
  303.     return;
  304.       }
  305.       s += len;
  306.       if (*s)
  307.     s++;
  308.     }
  309.   } else {            /* user-specified config file */
  310.     if (!*config_file_name)
  311.       return;
  312.     if (access(config_file_name, R_OK) != 0) {
  313.       warning("cannot open user-specified config file \"%s\"",
  314.           config_file_name);
  315.     } else {
  316.       in_config_file = 1;
  317.       process_file(config_file_name);
  318.       in_config_file = 0;
  319.     }
  320.   }
  321. }
  322.  
  323. /* main() -- guess... */
  324. main(argc, argv)
  325.   int argc;
  326.   char **argv;
  327. {
  328.   register int i;
  329.   char *infnam;
  330.   int num_Is = 3;
  331.   register char **cur_I, *incdir;
  332.   time_t t;
  333.   struct tm *T;
  334.  
  335.   argv0 = argv[0];
  336.   Z_type_init();
  337.   hash_setup();
  338.   cond_setup();
  339.   setup_signals();
  340.   time(&t);
  341.   T = localtime(&t);
  342.   strftime(date_string, 12, "%b %d %Y", T);
  343.   strftime(time_string, 9, "%H:%M:%S", T);
  344.   add_include((char *)0);
  345.   /* first check for user-specified config file */
  346.   for (i = 1; i < argc && *argv[i] == '-' && argv[i][1] != '\0'; i++)
  347.     if (*argv[i] == '-' && argv[i][1] == 'S')
  348.       config_file_name = argv[i] + 2;
  349.   Argc = argc;
  350.   Argv = argv;
  351.   do_config_file();
  352.   if (Argc_end == 0)
  353.     do_all_cmdline_args();
  354.   if ((incdir = getenv("INCLUDE"))) {
  355.     char *s = incdir;
  356.     size_t len;
  357.  
  358.     while (*s) {
  359.